package com.gitee.wsl.net.resource

import androidx.compose.runtime.Stable
import androidx.compose.ui.text.font.Font
import com.gitee.wsl.io.cache.CacheStrategy
import com.gitee.wsl.io.cache.DiskCacheStrategy
import com.gitee.wsl.resource.font.FontManager
import com.gitee.wsl.resource.font.FontSpec
import com.gitee.wsl.resource.font.makeFont

/**
 * Font manager that loads fonts from the web.
 *
 * Guaranteed to work only with [LottieFontSpec.FontOrigin.FontUrl] .ttf fonts
 * (support may be higher on non-Android platforms).
 *
 * Note: [LottieCacheStrategy.path] should return valid file system paths to make [NetworkFontManager] work.
 * Default [DiskCacheStrategy] supports it.
 *
 * @param cacheStrategy caching strategy. Caching to system temp dir by default
 * */

@Stable
fun NetworkFontManager(
    cacheStrategy: CacheStrategy = DiskCacheStrategy.Instance,
) : FontManager = NetworkFontManager(
    request = DefaultHttpRequest,
    cacheStrategy = cacheStrategy
)

fun FontManager.Companion.network(
    cacheStrategy: CacheStrategy = DiskCacheStrategy.Instance
    ) : FontManager = NetworkFontManager(
    cacheStrategy = cacheStrategy
)

/**
 * Font manager that loads fonts from the web using [request].
 *
 * Guaranteed to work only with [LottieFontSpec.FontOrigin.FontUrl] .ttf fonts
 * (support may be higher on non-Android platforms).
 *
 * Note: [LottieCacheStrategy.path] should return valid file system paths to make [NetworkFontManager] work.
 * Default [DiskCacheStrategy] supports it.
 *
 * @param request network request used for loading fonts
 * @param cacheStrategy caching strategy. Caching to system temp dir by default
 * */
@Stable
fun NetworkFontManager(
    request : suspend (url: String) -> ByteArray,
    cacheStrategy: CacheStrategy = DiskCacheStrategy.Instance,
) : FontManager = NetworkFontManagerImpl(
    request = request,
    cacheStrategy = cacheStrategy,
)

fun FontManager.Companion.network(
    request : suspend (url: String) -> ByteArray,
    cacheStrategy: CacheStrategy = DiskCacheStrategy.Instance
) : FontManager = NetworkFontManager(
    request = request,
    cacheStrategy =cacheStrategy
)

@Stable
private class NetworkFontManagerImpl(
    private val request : suspend (url: String) -> ByteArray,
    private val cacheStrategy: CacheStrategy,
) : FontManager {

    override suspend fun font(font: FontSpec): Font? {

        if (font.origin != FontSpec.FontOrigin.FontUrl){
            return null
        }

        val (path, bytes) = networkLoad(
            request = request,
            cacheStrategy = cacheStrategy,
            url = font.path ?: return null
        )

        if (path == null || bytes == null){
            return null
        }

        return makeFont(font, path, bytes)
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other == null || this::class != other::class) return false

        other as NetworkFontManagerImpl

        if (request != other.request) return false
        if (cacheStrategy != other.cacheStrategy) return false

        return true
    }

    override fun hashCode(): Int {
        var result = request.hashCode()
        result = 31 * result + cacheStrategy.hashCode()
        return result
    }
}


